﻿Public Class RealAlarmForm

    Private _pi As ProjectItem

    '报警记录的起始地址
    Private _offset As UShort = 19000

    '最大的报警记录数
    Private ReadOnly _RecodCound As Integer = 25

    '每条记录的字节数
    Private ReadOnly _RecodSize As Integer = 10

    Protected _dataLength As UShort = _RecodCound * _RecodSize / 2

    '报警记录列表
    Private _alarmItemList As IList(Of RealtimeAlarmItem) = New List(Of RealtimeAlarmItem)

    '报警记录数据
    Protected _buf() As Byte

    Private _netID As Byte = 255

    '窗体是否关闭
    Private _isClose As Boolean = False

    '正在发送确认消息
    Private _isConfirm As Boolean = False

    '正在刷新报警数据
    Private _isRefresh As Boolean = False

    Private Sub AlarmForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AlarmStatustip.Visible = False
        Me.DataGridView1.AutoGenerateColumns = False
        _pi = MainForm.pi
        'ProjectService.RefreshCurProjectList(_pi.ProjectID) '刷新当前工程信息
        Me.Timer1.Interval = 100 '第一次先进行刷新
        Me.Timer1.Start()
        'Timer1_Tick(Nothing, Nothing)
    End Sub


    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Me.Timer1.Interval = 3000 '之后的每次以3秒为间隔刷新

        If _isConfirm Then
            '正在发送确认数据，暂不刷新
            Exit Sub
        End If

        Me.Timer1.Stop()
        Try
            _isRefresh = True
            StartNewdataRefresh()
        Catch ex As Exception
            Debug.WriteLine(ex.ToString())
        Finally
            _isRefresh = False
        End Try

        If _isClose Then
            Exit Sub
        End If

        Me.Timer1.Start()
    End Sub

    '连续读取数据失败的次数
    Private _FailCount As Integer = 0

    ''' <summary>
    ''' 刷新报警数据
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub StartNewdataRefresh()
        Me.lblTip.Text = "正在读取数据..."

        ReadData()
        ParseData()

        Me.lblTip.Text = ""

        Try
            'If Me._alarmItemList Is Nothing OrElse Me._alarmItemList.Count = 0 Then
            If _buf Is Nothing Then
                _FailCount += 1
                If _FailCount >= 5 Then
                    Me.DataGridView1.DataSource = Nothing
                    AlarmStatustip.Visible = True
                End If
                Exit Sub
            Else
                _FailCount = 0
                AlarmStatustip.Visible = False
            End If

            Me.DataGridView1.DataSource = Nothing
            Me.DataGridView1.DataSource = Me._alarmItemList
            SetColor()
            Me.DataGridView1.Refresh()
        Catch ex As Exception
            Debug.Write(ex.ToString())
        End Try

    End Sub


    Protected Sub ReadData()
        '读所有实时报警数据
        Dim firstLength As UShort = _dataLength
        _buf = COMHelper.Instance.Send4Byte(_netID, FunctionCode.WordReadonly, Me._offset, firstLength)
    End Sub


    ''' <summary>
    ''' 数据解析
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub ParseData()
        _alarmItemList.Clear()

        If _buf Is Nothing Then
            Exit Sub
        End If

        Dim iMonth, iDay, iHour, iMinute, iSecond As Integer

        For i As Integer = 0 To _RecodCound - 1
            Dim item As New RealtimeAlarmItem
            item.ID = i
            item.netID = _buf(i * _RecodSize + 0)    '网络地址

            iMonth = _buf(i * _RecodSize + 1)
            iDay = _buf(i * _RecodSize + 2)
            iHour = _buf(i * _RecodSize + 3)
            iMinute = _buf(i * _RecodSize + 4)
            iSecond = _buf(i * _RecodSize + 5)

            If g_test Then
                iMonth = iMonth Mod 12 + 1
                iDay = iDay Mod 28 + 1
                iHour = iHour Mod 24
                iMinute = iMinute Mod 60
            End If


            If iMonth = 0 OrElse iDay = 0 OrElse iMonth = 255 OrElse iDay = 255 Then
                Continue For
            Else
                item.strTime = String.Format("{0}-{1} {2}:{3}:{4}", iMonth, iDay, iHour, iMinute, iSecond)
            End If

            item.typeID = _buf(i * _RecodSize + 6)   '报警类型
            item.Name = GetRefName(item.netID, item.typeID)

            If item.Name = String.Empty Then '无法解析冷库名称
                Continue For
            End If

            item.typeName = GetTypeName(item.netID, item.typeID, item.Name)   '报警显示名称
            If item.typeName = String.Empty Then '无法解析报警设备名称
                Continue For
            End If

            If g_test Then
                Dim aa() As Integer = {100, 101, 102, 103, 104, 105, 110, 120, 130, 140, 141, 142, 143, 144, 145, 150, 200, 201, 202, 203, 210, 211, 212, 213}
                item.typeID = aa(g_rand.Next(0, aa.Length))

                If item.typeID < 200 Then
                    item.netID = 1
                Else
                    item.netID = 2
                End If

            End If

            item.level = _buf(i * _RecodSize + 7) Mod 4   '报警级别

            item.IsValid = (_buf(i * _RecodSize + 8) Mod 3 = 2)  '是否有效

            'item.confirmed = (_buf(224 + i) Mod 3 = 2) '是否确认
            item.confirmed = (_buf(i * _RecodSize + 9) Mod 3 = 2) '是否确认

            If Not item.netID > 0 Then
                Debug.WriteLine("实时报警数据中存在无效的网络地址")
            End If

            _alarmItemList.Add(item)
        Next

    End Sub

    '获取冷库信息
    Private Function GetRefName(ByVal netid As Integer, ByVal typeid As Byte) As String

        Select Case typeid
            Case 130, 140, 150, 160 '缺项报警
                Return "系统"

            Case 131, 141, 151, 161 '冷库DI/DO报警
                Return ProjectService.GetRefName_FromRefid(_pi, netid, (typeid - 120) / 10)

            Case 100 To 123 '温湿度超高低限报警                
                Return ProjectService.GetRefName_FromPortNo(_pi, netid, Math.Truncate((typeid - 100 + 2) / 2))
            Case Else

        End Select

        Return ""

    End Function

    '获取报警显示名称
    Private Function GetTypeName(ByVal netid As Integer, ByVal typeid As Byte, ByVal refname As String) As String
        Dim PortName As String

        Select Case typeid
            Case 130 To 161 '冷库DI/DO报警
                If typeid Mod 10 = 0 Then '缺项输入报警

                    If ProjectService.GetDioStatus(_pi, netid, 1) = True Then
                        Return "缺项输入报警"
                    Else
                        Return ""
                    End If
                ElseIf typeid Mod 10 = 1 Then '库门报警

                    If ProjectService.GetDioStatus(_pi, netid, 2) = True Then
                        Return "库门报警"
                    Else
                        Return ""
                    End If
                End If

            Case 100 To 123 '温湿度超高低限报警                
                PortName = ProjectService.GetPortName_FromPortNo(_pi, netid, Math.Truncate((typeid - 100 + 2) / 2))
                If PortName = String.Empty Then
                    Return ""
                End If

                If typeid Mod 2 = 0 Then '超高限报警
                    Return (PortName & "超高限报警")
                End If

                If typeid Mod 2 = 1 Then '超低限报警
                    Return (PortName & "超低限报警")
                End If

            Case Else

        End Select

        Return ""

    End Function


    ''' <summary>
    ''' 双击dataGrid单元格
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Private Sub DataGridView1_CellDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellDoubleClick
        If Me._isRefresh Then
            Exit Sub
        End If

        If _isConfirm Then
            Exit Sub
        End If

        Try
            _isConfirm = True
            Me.ConfirmWarning()
        Catch ex As Exception
            MsgBox(ex.Message)
        Finally
            _isConfirm = False
        End Try
    End Sub


    ''' <summary>
    ''' 确认报警
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub ConfirmWarning()
        Debug.WriteLine("DataGridView1_CellDoubleClick + " & Now.ToLongTimeString())
        If Me.DataGridView1.CurrentRow Is Nothing Then
            Exit Sub
        End If

        If Me.DataGridView1.CurrentRow.Cells(6).Value = True Then
            Exit Sub
        End If

        Dim s As String
        s = Me.DataGridView1.CurrentRow.Cells(3).Value

        Dim tip As String
        tip = String.Format("是否要确认【{0}】", s)

        'Dim id As Integer = Me.DataGridView1.CurrentRow.Cells(1).Value

        Dim item As RealtimeAlarmItem = CType(Me.DataGridView1.CurrentRow.DataBoundItem, RealtimeAlarmItem)
        'Dim netid As Byte = item.netID
        'Dim typeid As Byte = item.typeID

        'If msg.ShowYesNo(tip) <> Windows.Forms.DialogResult.Yes Then
        '    Exit Sub
        'End If

        If AlarmConfirm(item) Then
            If Me.DataGridView1.CurrentRow Is Nothing Then
                Exit Sub
            End If
            Me.DataGridView1.CurrentRow.Cells(6).Value = True

            'Me.DataGridView1.CurrentRow.DefaultCellStyle.BackColor = Color.LightBlue
            Me.DataGridView1.CurrentRow.DefaultCellStyle.BackColor = Color.White
        Else
            msg.ShowError("确认报警标志失败")
        End If

    End Sub

    ''' <summary>
    ''' 设置报警确认标志
    ''' </summary>
    ''' <param name="item"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function AlarmConfirm(ByVal item As RealtimeAlarmItem) As Boolean
        '报警确认地址
        Dim offset As UShort = 7067

        '确认数据为 网络地址＋报警类型 （网络地址为高字节）
        Dim value As Short = item.netID * 256 + item.typeID

        '发送确认命令
        Return COMHelper.Instance.Write(_netID, FunctionCode.WordWrite, offset, value)
    End Function


    ''' <summary>
    ''' 清除所有报警标志
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function AlarmConfirmAll() As Boolean
        Dim offset As UShort = 7066
        Dim value As Short = 2
        Return COMHelper.Instance.Write(_netID, FunctionCode.WordWrite, offset, value)
    End Function

    ''' <summary>
    ''' 窗口关闭，停止刷新数据
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnClosing(ByVal e As System.ComponentModel.CancelEventArgs)
        _isClose = True
        MyBase.OnClosing(e)
    End Sub

    Private Sub btnClearAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClearAll.Click
        Dim result As Boolean
        _isConfirm = True
        result = Me.AlarmConfirmAll()
        _isConfirm = False
        If result Then
            For Each r As DataGridViewRow In Me.DataGridView1.Rows
                r.Cells(6).Value = True
            Next
            SetColor()
        Else
            msg.ShowError("确认报警标志失败")
        End If
    End Sub

    ''' <summary>
    ''' 设置数据行的颜色
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub SetColor()
        Try
            For Each r As DataGridViewRow In Me.DataGridView1.Rows
                '报警有效的记录显示为红色
                If r.Cells(5).Value = True Then
                    r.DefaultCellStyle.ForeColor = Color.Red
                Else
                    r.DefaultCellStyle.ForeColor = Color.Black
                End If

                '报警未确认的记录显示灰色背景颜色
                If r.Cells(6).Value = 0 Then
                    r.DefaultCellStyle.BackColor = Color.LightGray
                Else
                    r.DefaultCellStyle.BackColor = Color.White
                End If
            Next
            Me.DataGridView1.Refresh()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

    End Sub

    Private Sub DataGridView1_DataError(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
        e.ThrowException = False
        Me.DataGridView1.DataSource = Nothing
        Me.DataGridView1.Refresh()
    End Sub
End Class